package solutions.ferpa.ztest.intf;

import br.com.telescope.adsrt.dom.DomFlagYn;
import br.com.telescope.adsrt.dom.DomLogin;
import br.com.telescope.adsrt.dom.DomPasswordHash;
import br.com.telescope.adsrt.dom.DomText;
import br.com.telescope.adsrt.dom.DomTextHtml;
import br.com.telescope.adsrt.lib.*;
import br.com.telescope.auth.AdsrtSession;
import br.com.telescope.auth.AdsrtUser;
import br.com.telescope.auth.Session;
import br.com.telescope.auth.User;
import br.com.telescope.t2.AccessPolicy;
import br.com.telescope.t2.ServiceModel;
import br.com.telescope.t2.config.Config;
import br.com.telescope.t2.exception.ApplicationRuntimeException;
import br.com.telescope.t2.exception.UnexpectedException;
import br.com.telescope.t2.feature.CustomActionFeature;
import br.com.telescope.t2.feature.CustomFeature;
import br.com.telescope.util.HashUtil;
import br.com.telescope.util.URLParameters;
import java.util.Date;
import org.json.JSONException;
import org.json.JSONObject;
import solutions.ferpa.ztest.ent.*;

/**
 * Acesso ao sistema.
 * <p>
 * Interface que permite o usuário autenticar-se no sistema.
 * <P>
 * O usuário deverá informar seu nome de usuário e sua senha. Se os dados 
 * estiverem corretos, o usuário é autenticado na sessão do sistema e 
 * encaminhado para a tela de entrada de usuários autenticados.
 * <P>
 * Opcionalmente, o usuário poderá selecionar para que este computador 
 * autentique-o automaticamente. Neste processo, a senha não fica 
 * armazenada no computador, mas sim uma chave de autorização que fica 
 * associada ao seu usuário.
 * <P>
 * 
 * <P>
 * Telescope origin: RTAUTH.PRO_LOGIN
 * <P>
 * @author TELESCOPE - Build task T2 Web Interface Generator
 * <P>
 * @version 0.1
 */
public class ProLogin extends ServiceModel {
    
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    public static final String GLOBAL_NAME = "RTAUTH.PRO_LOGIN";
    
    @Override
    public String globalName() {
        return GLOBAL_NAME;
    }
    
    {
        setTitle("Acesso ao sistema");
    }
    
    
    // Record items
    private DomText aRediParams;
    private DomText aRediService;
    private DomLogin aUsuario;
    private DomPasswordHash aSenha;
    private DomFlagYn aContinuarConectado;
    private DomTextHtml aMensagem;
    
    // Query items
    
    @Override
    public void initAttributes() {
        
        aRediParams = new DomText();
        aRediParams.context(ctx).name("REDI_PARAMS").label(" ").unbound(true);
        
        aRediService = new DomText();
        aRediService.context(ctx).name("REDI_SERVICE").label(" ").unbound(true);
        
        aUsuario = new DomLogin();
        aUsuario.context(ctx).name("USUARIO").label("Usuário").width(15).unbound(true);
        
        aSenha = new DomPasswordHash();
        aSenha.context(ctx).name("SENHA").label("Senha").width(15).unbound(true);
        
        aContinuarConectado = new DomFlagYn();
        aContinuarConectado.context(ctx).name("CONTINUAR_CONECTADO").label("Continuar conectado").unbound(true);
        aContinuarConectado.setDefaultValue("Y");
        
        aMensagem = new DomTextHtml();
        aMensagem.context(ctx).name("MENSAGEM").label("").unbound(true);
        
    }
    
    @Override
    public String getDefaultOrderBy() {
        return "";
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="ENTRADA">
    public class FEntrada extends CustomFeature {
        
        @Override
        public void initForm() {
            aRediParams.setHidden(true);
            addField(aRediParams, "hidden");
            aRediService.setHidden(true);
            addField(aRediService, "hidden");
            aUsuario.setOptional(false);
            addField(aUsuario, "rqd");
            aSenha.setOptional(false);
            addField(aSenha, "rqd");
            addField(aContinuarConectado, "opt");
            aMensagem.setEditable(false);
            addField(aMensagem, "view");
        }
        
        @Override
        public int getAccessPolicy() {
            return AccessPolicy.PUBLIC;
        }
        
        @Override
        public void preDisplay() {
            try {
                
                apresentarOpcaoCriarContaEAlterarSenha();
                apresentarInstrucoesEspecificas();
                preencherHidden();
                criaSessao();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        @Override
        public void onAction() {
            addSubmit(getFeature("PERFORM_LOGIN")).label("Entrar");
        }
        
        {
            setFeatureName("ENTRADA");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="PERFORM_LOGIN">
    public class FPerformLogin extends CustomFeature {
        
        @Override
        public void initForm() {
        }
        
        @Override
        public int getAccessPolicy() {
            return AccessPolicy.PUBLIC;
        }
        
        @Override
        public void preDisplay() {
            try {
                executeLogin();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("PERFORM_LOGIN");
            setTitle("Entrar");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="DESBLOQUEAR">
    public class FDesbloquear extends CustomActionFeature {
        
        @Override
        public void initForm() {
        }
        
        @Override
        public int getAccessPolicy() {
            return AccessPolicy.PUBLIC;
        }
        
        @Override
        public void execute() {
            try {
                desbloquear();
            } catch (AdsException ex) {
                throw new ApplicationRuntimeException(ex);
            }
        }
        
        {
            setFeatureName("DESBLOQUEAR");
            setTitle("Desbloquear");
            setPrimary(false);
        }
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="initFeatures">
    
    @Override
    protected void initFeatures() {
        addFeature(new FEntrada());
        addFeature(new FPerformLogin());
        addFeature(new FDesbloquear());
        super.initFeatures();
    }
    
    @Override
    public String getDefaultFeature() {
        return "ENTRADA";
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Getters and Setters">
    
    public String getRediParams() {
        return aRediParams.getValue();
    }
    
    public void setRediParams(String value) {
        this.aRediParams.setValue(value);
    }
    
    public String getRediService() {
        return aRediService.getValue();
    }
    
    public void setRediService(String value) {
        this.aRediService.setValue(value);
    }
    
    public String getUsuario() {
        return aUsuario.getValue();
    }
    
    public void setUsuario(String value) {
        this.aUsuario.setValue(value);
    }
    
    public String getSenha() {
        return aSenha.getValue();
    }
    
    public void setSenha(String value) {
        this.aSenha.setValue(value);
    }
    
    public String getContinuarConectado() {
        return aContinuarConectado.getValue();
    }
    
    public void setContinuarConectado(String value) {
        this.aContinuarConectado.setValue(value);
    }
    
    public String getMensagem() {
        return aMensagem.getValue();
    }
    
    public void setMensagem(String value) {
        this.aMensagem.setValue(value);
    }
    // </editor-fold>
    
    /**
     * Desbloquear.
     * <p>
     * Ação que é utilizada quando a sessão do usuário expira e a interface 
     * abre um diálogo de desbloqueio. A função recebe o hash da senha 
     * informada e retorna um OK ou ERRO.
     * <P>
     */
    public void desbloquear() throws AdsException {
        // <user-code id="20962646" parentId="20962643" hashcode="-1a1b2ad" length="600">
        // import org.json.JSONObject;
        // import org.json.JSONException;
        
        String username = ctx.getParameter("A_USUARIO").toLowerCase();
        String password = ctx.getParameter("A_SENHA");
        
        boolean success = false;
        
        if (username.length() > 0) {
            EntUsuarios user = new EntUsuarios(ctx);
            user.findByLogin(username);
            if (password.equals(user.valueOfSenhaHash())) {
                login(user, false);
                success = true;
            }
        }
        
        JSONObject json = new JSONObject();
        try {
            json.put("success", success);
        } catch (JSONException ignore) {
        }
        setShown(true);
        ctx.output(json.toString());
        // </user-code>
    }
    
    /**
     * Apresentar instruções específicas.
     * <p>
     * Apresenta alguma informação específica que se deseja apresentar na 
     * tela de login.
     * <P>
     * Esta informação é apresentada antes do formulário de login e é pode 
     * ser configurada na preferencia [t:#14230138].
     * <P>
     */
    private void apresentarInstrucoesEspecificas() throws AdsException {
        // <user-code id="14230143" parentId="14230130" hashcode="-533a4c96" length="117">
        String msg = Config.getInstance().getParameter("RTAUTH.PRO_LOGIN.MSG_LOGIN");
        if (msg != null) {
            ctx.p(msg);
        }
        // </user-code>
    }
    
    /**
     * Apresentar opção para criar conta e alterar senha.
     * <p>
     * Apresenta a mensagem e link para criar conta e a chave de ativação, 
     * também apresentar uma opção de poder recuperar a senha
     * <P>
     * Verifica se deve apresentar o campo de memorizar senha, baseado na 
     * preferencia RTAUTH_PESS.PRO_LOGIN.MOMORIZAR_SENHA
     */
    private void apresentarOpcaoCriarContaEAlterarSenha() throws AdsException {
        // <user-code id="794345" parentId="794341" hashcode="-3ea4f79d" length="837">
        StringBuilder html = new StringBuilder(1000);
        try {
            if (ctx.getPreference("RTAUTH.RECOVERY_PASSWORD", "S").equals("S")) {
                html.append("<div class=\"recovery-password\"><a tabindex=\"-1\" href=\"")
                        .append(ctx.getServiceUrl("RTAUTH.REQ_ALT_SENHA"))
                        .append("\">Recuperar senha</a></div>");
            }
            
            if (ctx.getPreference(globalName("MEMORIZAR_SENHA"), "S").equals("N")) {
                aContinuarConectado.setHidden(true);
            }
        
            if (ctx.getPreference("RTAUTH.CREATE_ACCOUNT", "N").equals("S")) {
                html.append("<div class=\"create-account\"><a tabindex=\"-1\" href=\"")
                        .append(ctx.getServiceUrl("RTAUTH.CRIA_CONTA"))
                        .append("\">Criar conta</div>");
            }
        } catch (Exception ignore) {
            
        }
        
        aMensagem.setValue(html.toString());
        // </user-code>
    }
    
    /**
     * Cria sessão.
     */
    private void criaSessao() throws AdsException {
        // <user-code id="820736" parentId="820732" hashcode="5e0" length="2">
        //
        // </user-code>
    }
    
    /**
     * Execute login.
     */
    private void executeLogin() throws AdsException {
        // <user-code id="777938" parentId="777936" hashcode="-3b8a3dd0" length="4343">
        // import br.com.telescope.util.HashUtil;
        // import br.com.telescope.auth.AdsrtUser;
        // import br.com.telescope.t2.config.Config;
        // import br.com.telescope.t2.exception.UnexpectedException;
        // import br.com.telescope.auth.AdsrtSession;
        // import br.com.telescope.util.URLParameters;
        // import java.util.Date;
        // import br.com.telescope.auth.Session;
        String userName = ctx.getParameter("A_USUARIO").toLowerCase();
        String senha = ctx.getParameter("A_SENHA");
        String lembrar = ctx.getParameter("A_CONTINUAR_CONECTADO");
        boolean ok = false;
        AdsrtSession session = (AdsrtSession) ctx.getSession();
        Config cfg = Config.getInstance();
        if (userName.length() > 0) {
            session.setObject("MENU", null); // Limpa o menu do cache
            try {
                EntUsuarios user = new EntUsuarios(ctx);
                user.findByLogin(userName);
                if (senha.equals(user.valueOfSenhaHash())) {
                    if (user.valueOfAtivo().equals("S")) {
                        login(user, lembrar.equals("S"));
                        // Se tiver data de validade
                        if (user.getValidade().isNotNull()) {
                            // E ela for inferior a data de hoje
                            if (user.valueOfValidade().compareTo(new Date()) <= 0) {
                                ctx.pushError(new AdsException("", 
                                        AdsException.WARNING, "Favor alterar a senha!"));
                                AltSenha external = new AltSenha();
                                external.setRuntime(ctx);
                                external.init();
                                external.getFeature("CUSTOM").run();
                                ok = true;
                            } else {
                                String rediParams = ctx.getParameter("A_REDI_PARAMS");
                                String rediService = ctx.getParameter("A_REDI_SERVICE");
                                if (!rediParams.isEmpty() && !rediService.isEmpty()) {
                                    URLParameters params = new URLParameters();
                                    params.setURLParameters(rediParams);
                                    openInterface(rediService, params);
                                } else {
                                    openInterface(cfg.getParameter("RT.UI.USER_HOME", "HOME"));
                                }
                            }
        
                        } else {
                            String rediParams = ctx.getParameter("A_REDI_PARAMS");
                            String rediService = ctx.getParameter("A_REDI_SERVICE");
                            if (!rediParams.isEmpty() && !rediService.isEmpty()) {
                                URLParameters params = new URLParameters();
                                params.setURLParameters(rediParams);
                                openInterface(rediService, params);
                            } else {
                                openInterface(cfg.getParameter("RT.UI.USER_HOME", "HOME"));
                            }
                        }
                    } else {
                        pushError("INACTIVE_USER", message("RTAUTH.INACTIVE_USER", "Usuário inativo!"));
                    }
                } else {
                    pushError("USER_NOT_FOUND", message("RTAUTH.USER_NOT_FOUND", "Usuário e/ou senha estão incorretos"));
                }
            } catch (RecordNotFoundException ex) {
                pushError("USER_NOT_FOUND", message("RTAUTH.USER_NOT_FOUND", "Usuário e/ou senha estão incorretos"));
            } catch (Exception ex) {
                String adminUser = cfg.getParameter("CONFIG.INSTALL_USER", "install");
                String adminPassword = cfg.getParameter("CONFIG.INSTALL_PASSWORD", "telescope");
                String apHash = HashUtil.getSha1(adminPassword);
                if (adminUser.equals(userName) && apHash.equals(senha)) {
                    AdsrtUser auser = new AdsrtUser();
                    auser.setDisplayName("Installation User");
                    auser.setId("0");
                    auser.setLoginName(adminUser);
                    auser.setSuperUser(true);
                    session.login(auser);
                    openInterface(cfg.getParameter("CONFIG.INSTALL_HOME", "RTCONFIG.CFG_CONFIG"));
                } else {
                    pushError("INSTALLATION_USER_NOT_FOUND", 
                            message("RTAUTH.INSTALLATION_USER_NOT_FOUND", "Usuário de instalação ou senha estão incorretos"));
                }
            }
        }
        String tz = ctx.getParameter("A_TIME_ZONE");
        ctx.setTimeZone(tz);
        ctx.setSessionString("TIME_ZONE", tz);
        if (!ok) getFeature("ENTRADA").run();
        // </user-code>
    }
    
    /**
     * Login.
     */
    // <user-code id="20962659" parentId="20962658" hashcode="202d1e43" length="968">
    public void login(EntUsuarios user, boolean remember) throws AdsException {
        AdsrtSession session = (AdsrtSession) ctx.getSession();
        AdsrtUser auser = new AdsrtUser();
        auser.setDisplayName(user.valueOfNomeCompleto());
        auser.setEmail(user.valueOfEMail());
        auser.setId(String.valueOf(user.valueOfId()));
        auser.setLoginName(user.valueOfLogin());
        auser.setSuperUser(user.valueOfSuperUsuario().equals("S"));
        auser.setPersonId(user.valueOfPessoaId());
        session.login(auser);
        //if (remember.equals("S") && ctx.getPreference(globalName("MEMORIZAR_SENHA"), "S").equals("S")) {
        if (remember && ctx.getPreference(globalName("MEMORIZAR_SENHA"), "S").equals("S")) {
            EntBilhetesEntrada bil = new EntBilhetesEntrada(ctx);
            bil.setUsuarioId(user.valueOfId());
            bil.ins();
            session.getCurrentUser().setRememberMe(true);
            ctx.setCookie(session.getCookieName(), bil.valueOfCodigo());
        }
    }
    // </user-code>
    
    /**
     * Preencher hidden.
     */
    private void preencherHidden() throws AdsException {
        // <user-code id="820654" parentId="820649" hashcode="7320bc00" length="116">
        aRediParams.setValue(ctx.getParameter("A_REDI_PARAMS"));
        aRediService.setValue(ctx.getParameter("A_REDI_SERVICE"));
        // </user-code>
    }
}
